package com.seeyon.apps.cxgd.kit;

import com.seeyon.cap4.form.bean.*;
import com.seeyon.cap4.form.bean.context.CalcContextBean;
import com.seeyon.cap4.form.modules.engin.base.formData.CAP4FormDataManager;
import com.seeyon.cap4.form.service.CAP4FormManager;
import com.seeyon.ctp.common.AppContext;
import com.seeyon.ctp.common.ModuleType;
import com.seeyon.ctp.common.authenticate.domain.User;
import com.seeyon.ctp.common.content.mainbody.CtpContentAllBean;
import com.seeyon.ctp.common.content.mainbody.MainbodyService;
import com.seeyon.ctp.common.content.mainbody.MainbodyStatus;
import com.seeyon.ctp.common.content.mainbody.MainbodyType;
import com.seeyon.ctp.common.exceptions.BusinessException;
import com.seeyon.ctp.common.log.CtpLogFactory;
import com.seeyon.ctp.common.po.content.CtpContentAll;
import com.seeyon.ctp.organization.bo.V3xOrgMember;
import com.seeyon.ctp.util.DateUtil;
import com.seeyon.ctp.util.UUIDLong;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.logging.Log;

import java.sql.SQLException;
import java.sql.Timestamp;
import java.util.*;

public class FormCap4Kit {

    private static final Log log = CtpLogFactory.getLog(FormCap4Kit.class);
    private static CAP4FormManager cap4FormManager = (CAP4FormManager) AppContext.getBean("cap4FormManager");

    private static CAP4FormDataManager cap4FormDataManager = (CAP4FormDataManager) AppContext.getBean("cap4FormDataManager");


    /**
     * 添加无流程表单数据及附件信息。
     * 此方法用于处理无流程的表单数据的添加操作，包括表单主数据的插入或更新，
     * 以及表单正文内容的保存。如果当前用户存在，则使用当前用户ID，
     * 否则使用表单创建者ID作为操作人ID。
     *
     * @param formDataMasterBean 表单主数据对象，包含要插入或更新的表单主数据信息。
     * @param formBean           表单详细数据对象，包含表单的权限视图信息和正文内容等。
     */
    public static void addUnFlowFormDataCap4(FormDataMasterBean formDataMasterBean, FormBean formBean) {
        try {
            // 尝试获取当前操作用户
            User user = AppContext.getCurrentUser();
            // 初始化用户ID变量，并尝试从当前用户获取用户ID
            Long userId = null;
            if (user != null) {
                userId = user.getId();
            }
            // 如果当前用户ID为空，则使用表单创建者ID
            if (userId == null) {
                userId = formBean.getCreatorId();
            }
            // 获取表单的权限视图信息，用于后续的操作权限判断
            FormAuthViewBean formAuthViewBean = formBean.getNewFormAuthViewBeans().get(0);
            // 将权限视图ID转换为字符串格式
            String rightid = String.valueOf(formAuthViewBean.getId());

            // 先插入或更新表单主数据
            cap4FormDataManager.insertOrUpdateMasterData(formDataMasterBean);
            // 获取刚刚插入或更新的表单主数据的ID
            Long masterId = formDataMasterBean.getId();

            // 确定表单模块类型，用于后续的正文内容处理
            int moduleType = getModuleTypeCap4(formBean);
            // 获取主body服务实例，用于保存正文内容
            MainbodyService mainBodyService = MainbodyService.getInstance();
            // 根据模块类型和主数据ID获取表单的正文内容
            CtpContentAll ctpContentAll = mainBodyService.getContent(moduleType, masterId);
            // 对获取到的正文内容进行加工或更新，同时设置操作人ID和权限视图ID
            ctpContentAll = saveContentAllForFormCap4(ctpContentAll, masterId, userId, formBean, rightid);
            // 保存或更新加工后的正文内容
            mainBodyService.saveOrUpdateContentAll(ctpContentAll);
        } catch (Exception e) {
            // 捕获并记录操作中可能出现的异常
            log.error("新增无流程表单数据报错信息:", e);
        }
    }


    /**
     * 保存表单内容信息。
     * 该方法用于处理表单内容的保存逻辑，包括新内容的创建和已有内容的更新。
     *
     * @param ctpContentAll 当前的内容信息，如果为null，则表示需要创建新内容。
     * @param masterId      主数据ID，用于关联内容和主数据。
     * @param userid        修改人ID，用于记录内容的修改者。
     * @param formBean      表单bean，包含表单的绑定信息和模块类型。
     * @param rightId       权限ID，用于记录内容的权限信息。
     * @return 返回保存或更新后的表单内容信息。
     * @throws BusinessException 如果没有应用绑定，则抛出业务异常。
     */
    private static CtpContentAll saveContentAllForFormCap4(CtpContentAll ctpContentAll, long masterId, long userid, FormBean formBean, String rightId) throws BusinessException {
        // 获取当前时间戳，用于记录创建或修改时间。
        Timestamp timestamp = DateUtil.currentTimestamp();
        // 如果ctpContentAll不为空，则进行更新操作。
        if (ctpContentAll != null) {
            // 更新修改人ID和修改时间。
            ctpContentAll.setModifyId(userid);
            ctpContentAll.setModifyDate(timestamp);
            return ctpContentAll;
        }
        // 创建新内容。
        CtpContentAllBean content = new CtpContentAllBean();
        // 获取表单的绑定信息。
        FormBindBean bindBean = formBean.getBind();
        if (bindBean != null) {
            // 设置模块模板ID。
            content.setModuleTemplateId(bindBean.getId());
            // 获取绑定授权信息。
            Map<String, FormBindAuthBean> bindAuth = bindBean.getUnFlowTemplateMap();
            // 如果没有绑定授权信息，则抛出业务异常。
            if (CollectionUtils.isEmpty(bindAuth.values())) {
                throw new BusinessException("无应用绑定");
            }
            // 遍历绑定授权信息，设置内容的标题。
            for (FormBindAuthBean authBean : bindAuth.values()) {
                content.setTitle(authBean.getName());
            }
        }
        // 设置模块类型。
        content.setModuleType(getModuleTypeCap4(formBean));
        // 设置创建人ID和创建时间。
        content.setCreateId(userid);
        content.setCreateDate(timestamp);
        // 设置排序字段。
        content.setSort(0);
        // 设置内容的唯一ID。
        content.setId(UUIDLong.longUUID());
        // 设置内容的状态。
        content.setStatus(MainbodyStatus.STATUS_POST_SAVE);
        // 设置内容的类型。
        content.setContentType(Integer.valueOf(MainbodyType.FORM.getKey()));
        // 设置内容模板ID。
        content.setContentTemplateId(formBean.getId());
        // 设置内容数据ID。
        content.setContentDataId(masterId);
        // 设置模块ID。
        content.setModuleId(masterId);
        // 更新修改时间。
        content.setModifyDate(timestamp);
        // 更新修改人ID。
        content.setModifyId(userid);
        // 设置权限ID。
        content.setRightId(rightId);
        // 将内容bean转换为内容all对象并返回。
        return content.toContentAll();
    }


    /**
     * 根据表单类型获取模块类型常量值。
     * 此方法专门处理表单类型为6的情况，映射到相应的模块类型常量。
     * 如果表单类型不是6，则认为是无效的表单类型，抛出业务异常。
     *
     * @param formBean 表单bean对象，包含表单类型信息。
     * @return 返回模块类型常量的整型值。
     * @throws BusinessException 如果表单类型无效，则抛出业务异常。
     */
    private static int getModuleTypeCap4(FormBean formBean) throws BusinessException {
        /* 初始化模块类型为0，表示默认状态 */
        int moduleType = 0;
        /* 判断表单类型是否为6 */
        if (formBean.getFormType() == 6) {
            /* 如果是，則将模块类型设置为cap4UnflowForm对应的键值 */
            moduleType = ModuleType.cap4UnflowForm.getKey();
        }
        /* 如果模块类型仍然为0，说明表单类型不是6，视为无效表单类型 */
        if (moduleType == 0) {
            /* 记录日志警告无效的表单类型 */
            log.warn("无效表类型");
            /* 抛出业务异常，提示内容保存失败 */
            throw new BusinessException("内容保存失败");
        }
        /* 返回计算得到的模块类型 */
        return moduleType;
    }




    /**
     * 保存表单数据
     * @param member           操作人员
     * @param tempCode         表单模板编号
     * @param mapDataList
     * @param isJxGs           判断是否计算控件的计算公式  true 是  false  否
     * @return
     */
    public static Boolean saveCAP4FormData(V3xOrgMember member, String tempCode, List<HashMap<String, Object>> mapDataList, Boolean isJxGs) {
        Boolean isSave = false;
        // 需要保存的底表数据
        List<FormDataMasterBean> masterdatas = new ArrayList<>();
        FormBean bean;
        try {
            bean = cap4FormManager.getFormByFormCode(tempCode);
        } catch (BusinessException e) {
            log.info("根据模板编号获取表单数据异，模板编号为：" + tempCode);
            return isSave;
        }
        //主表
        FormTableBean formTableBean = bean.getMasterTableBean();
        //明细表
        List<FormTableBean> subTableBeanList = bean.getSubTableBean();

        //获取表中所有字段信息
        List<FormFieldBean> fieldList = formTableBean.getFields();

        Map<String, FormFieldBean> fields = new HashMap<>();
        // 所有字段的集合
        for (FormFieldBean field : fieldList) {
            fields.put(field.getDisplay(), field);
        }

        //循环获取需要保存的数据
        for (HashMap<String, Object> mapData : mapDataList) {
            //获取主表数据
            HashMap<String, Object> masterData = (HashMap<String, Object>) mapData.get("masterData");
            //添加主表信息
            FormDataMasterBean dataMasterBean = FormDataMasterBean.newInstance(bean);
            for (String s : masterData.keySet()) {
                Set<String> strings = fields.keySet();
                if (strings.contains(s)) {
                    FormFieldBean formFieldBean = fields.get(s);
                    dataMasterBean.addFieldValue(formFieldBean.getName(), masterData.get(s));
                }
            }

            //获取明细表数据
            Object mxDataObject = mapData.get("mxData");
            if (mxDataObject != null) {
                HashMap<String, List<HashMap<String, Object>>> mxData = (HashMap<String, List<HashMap<String, Object>>>) mxDataObject;
                for (String s : mxData.keySet()) {
                    for (FormTableBean tableBean : subTableBeanList) {
                        String subTableName = tableBean.getTableName();
                        //                        String display = tableBean.getDisplay();
                        if (subTableName.equals(s)) {
                            //添加明细表数据
                            List<HashMap<String, Object>> hashMaps = mxData.get(s);
                            List<FormDataSubBean> subDatas = new ArrayList<>();
                            for (HashMap<String, Object> map : hashMaps) {
                                HashMap<String, Object> subData = new HashMap<>();
                                for (String s1 : map.keySet()) {
                                    subData.put(tableBean.getFieldBeanByDisplay(s1).getName(), map.get(s1));
                                }
                                FormDataSubBean formDataSubBean = new FormDataSubBean(subData, tableBean, dataMasterBean, false);
                                formDataSubBean.setIdIfNew();
                                formDataSubBean.setFormmainId(dataMasterBean.getId());
                                subDatas.add(formDataSubBean);
                            }
                            dataMasterBean.setSubData(tableBean.getTableName(), subDatas);
                        }
                    }
                }
            }
            try {
                saveContent(bean, dataMasterBean.getId(), member.getId());
            } catch (BusinessException e) {
                log.info("添加正文失败：" + e);
            }
            masterdatas.add(dataMasterBean);
        }
        try {
            //添加表单数据
            cap4FormDataManager.insertOrUpdateMasterData(masterdatas, false);
            log.info("保存档案表数据成功！！！！！！！！！"+isJxGs);
            //刷新计算公式
            if(isJxGs){
                log.info("保存档案表开始刷新计算公式！！！！！！！！！");
                for (FormDataMasterBean masterdata : masterdatas) {
                    calcAll(bean,masterdata,false,true,true,false);
                    log.info("保存档案表刷新计算公式成功！！！！！！！！！");
                }
                log.info("保存档案表结束刷新计算公式！！！！！！！！！");
            }
            isSave = true;
        } catch (BusinessException e) {
            throw new RuntimeException(e);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
        return isSave;
    }


    /**
     * 刷新表单计算公式
     * @param bean
     * @param masterdata
     * @param dealDefaultVal        是否需要带出初始值
     * @param needCalSN             是否需要计算流水号
     * @param needDealSysRelation   是否需要刷新系统条件类型的关联表单
     * @param needFillBack          是否要构造返回值
     */
    public static void calcAll(FormBean bean,FormDataMasterBean masterdata, boolean needFillBack, boolean needCalSN, boolean needDealSysRelation, boolean dealDefaultVal){
        log.info("开始刷新计算公式！！！！！！！！！");
        FormAuthViewBean auth = bean.getNewFormAuthViewBean();
        try {
            cap4FormDataManager.calcAll(new CalcContextBean(bean, auth),masterdata,needFillBack,needCalSN,needDealSysRelation,dealDefaultVal);
            cap4FormDataManager.insertOrUpdateMasterData(masterdata);
            log.info("结束刷新计算公式！！！！！！！！！");
        } catch (Exception e) {
            log.info("刷新计算公式异常！！！！！！！！！");
        }
    }


    /**
     * 保存表单正文信息
     * @param bean
     * @param moduleId
     * @param memberId
     * @return
     */
    private static void saveContent(FormBean bean, Long moduleId, Long memberId) throws BusinessException {
        CtpContentAll ctpContentAll = null;
        CtpContentAllBean ctpContentAllBean=null;
        FormAuthViewBean formAuthViewBean = bean.getNewFormAuthViewBeans().get(0);
        String rightid = String.valueOf(formAuthViewBean.getId());
        log.info("saveMasterAndSubForm finish masterId " + moduleId);
        //正文内容保存
        ctpContentAll = saveContentAllForForm(null, moduleId, memberId, bean,rightid);
        MainbodyService mainBodyService = MainbodyService.getInstance();
        mainBodyService.saveOrUpdateContentAll(ctpContentAll);
    }


    /**
     * 封装获取ContentAll数据
     * @param ctpContentAll
     * @param masterId
     * @param userid
     * @param formBean
     * @param rightId
     * @return
     * @throws BusinessException
     */
    private static CtpContentAll saveContentAllForForm(CtpContentAll ctpContentAll, long masterId, long userid,
                                                       FormBean formBean,String rightId) throws BusinessException {
        Timestamp timestamp = DateUtil.currentTimestamp();
        if (ctpContentAll != null) {
            ctpContentAll.setModifyId(userid);
            ctpContentAll.setModifyDate(timestamp);
            return ctpContentAll;
        }
        CtpContentAllBean content = new CtpContentAllBean();

        FormBindBean bindBean = formBean.getBind();
        if (bindBean != null) {
            content.setModuleTemplateId(bindBean.getId());
            Map<String, FormBindAuthBean> bindAuth = bindBean.getUnFlowTemplateMap();
            if (CollectionUtils.isEmpty(bindAuth.values())) {
                throw new BusinessException("无应用绑定");
            }
            for (FormBindAuthBean authBean : bindAuth.values()) {
                content.setTitle(authBean.getName());
            }
        }
        content.setModuleType(getModuleTypeCap4(formBean));
        content.setCreateId(userid);
        content.setCreateDate(timestamp);
        content.setSort(0);
        content.setId(UUIDLong.longUUID());
        content.setStatus(MainbodyStatus.STATUS_POST_SAVE);
        content.setContentType(Integer.valueOf(MainbodyType.FORM.getKey()));
        content.setContentTemplateId(formBean.getId());
        content.setContentDataId(masterId);
        content.setModuleId(masterId);
        content.setModifyDate(timestamp);
        content.setModifyId(userid);
        content.setRightId(rightId);

        return content.toContentAll();
    }

}
